package com.jule.teenpatti.game.service;

import com.jule.teenpatti.base.model.RoomTableRelationModel;
import com.jule.teenpatti.game.model.TimerKey;
import com.jule.teenpatti.game.network.protocol.TableInnerReq;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 房间倒计时调度服务
 */
@Slf4j
public class TimerService {
    private static final Map<TimerKey, TableInnerReq> EXPIRABLES = new ConcurrentHashMap<>();

    private static class SingletonHolder {
        protected static final TimerService instance = new TimerService();
    }

    public static final TimerService getInstance() {
        return SingletonHolder.instance;
    }

    public TimerService() {
        //定时循环查找超时的Timer
        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
            long timeNow = System.currentTimeMillis();
            int timerCnt = 0;
            try {
                //TableInnerReq
                synchronized (EXPIRABLES) {
                    timerCnt = EXPIRABLES.size();
                    for (Map.Entry<TimerKey, TableInnerReq> entry : EXPIRABLES.entrySet()) {
                        if (entry == null || entry.getKey() == null) {
                            log.error("Found Timer is null, entryIsNull={}, entry.getKey()IsNull={}",
                                    null == entry, null == entry ? "NULL" : entry.getKey() == null);
                            continue;
                        }
                        long endTime = entry.getKey().time;
                        TableInnerReq tableInnerReq = entry.getValue();
                        if (timeNow - endTime >= 0) {
                            EXPIRABLES.remove(entry.getKey());
                            tableInnerReq.sendToSelf();
                        }
                    }
                }
            } catch (Exception e) {
                log.error("TimerService() 循环查找超时Timer ERROR, msg->{}", e.getMessage(), e);
            } finally {
                if(System.currentTimeMillis() - timeNow >= 200) {
                    log.error("TimerService 循环查找超时Timer，耗时 {} 毫秒, timerCnt->{}", System.currentTimeMillis() - timeNow, timerCnt);
                }
            }
        }, 0, 1000, TimeUnit.MILLISECONDS);

        //定时查找超时应离桌的玩家
        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
            try {
                TableService.getInstance().timeOutLeaveTable();
            } catch (Exception e) {
                log.error("TimerService() 查找超时玩家 ERROR, msg->{}", e.getMessage(), e);
            }
        }, 0, 1000, TimeUnit.MILLISECONDS);
    }


    /**
     * 增加一个倒计时的任务
     *
     * @param endTime       倒计时的时间
     * @param tableInnerReq
     */
    public void addTimerTask(long endTime, RoomTableRelationModel relationModel, final TableInnerReq tableInnerReq) {
        long timeNow = System.currentTimeMillis();
        try {
//            delTimerTask(relationModel);
            synchronized (EXPIRABLES) {
                long _endTime = System.currentTimeMillis() + endTime * 1000;
                EXPIRABLES.put(new TimerKey(_endTime, relationModel), tableInnerReq);
            }
        }catch (Exception ex){
            log.error("addTimerTask ERROR, msg->{}", ex.getMessage());
        } finally {
//            lock.unlock();
            if(System.currentTimeMillis() - timeNow >= 100) {
                log.error("addTimerTask，耗时 {} 毫秒", System.currentTimeMillis() - timeNow);
            }
        }
    }

    /**
     * 删除一个倒计时的任务
     * <p>
     * //     * @param tableId 倒计时的时间
     */
    public void delTimerTask(RoomTableRelationModel relationModel) {
        long timeNow = System.currentTimeMillis();
        try {
            synchronized (EXPIRABLES) {
                TimerKey timerKey = new TimerKey(relationModel);
                EXPIRABLES.remove(timerKey);
            }
        }catch (Exception ex){
            log.error("delTimerTask ERROR, msg->{}", ex.getMessage());
        }finally {
            if(System.currentTimeMillis() - timeNow >= 100) {
                log.error("delTimerTask，耗时 {} 毫秒", System.currentTimeMillis() - timeNow);
            }
        }
    }

    public int getLeftCountDown(RoomTableRelationModel relationModel) {
        long timeNow = System.currentTimeMillis();
        try {
            synchronized (EXPIRABLES) {
                for (Map.Entry<TimerKey, TableInnerReq> entry : EXPIRABLES.entrySet()) {
                    if (entry == null || entry.getKey() == null) {
                        log.error("getLeftCountDown(),Found Timer is null, entryIsNull={}, entry.getKey()IsNull={}",
                                null == entry, null == entry ? "NULL" : entry.getKey() == null);
                        continue;
                    }
                    TimerKey timerKey = entry.getKey();
                    if (timerKey.hashCode() == relationModel.hashCode()) {
                        long endTime = entry.getKey().time;
                        return (int) ((endTime - timeNow) / 1000);
                    }
                }
            }
        } catch (Exception ex) {
            log.error("getLeftCountDown ERROR, msg->{}", ex.getMessage(), ex);
        }finally {
            if(System.currentTimeMillis() - timeNow >= 100) {
                log.error("getLeftCountDown 循环timer，耗时 {} 毫秒", System.currentTimeMillis() - timeNow);
            }
        }
        return 0;
    }

}
